home *** CD-ROM | disk | FTP | other *** search
/ Gigarom 1 / Gigarom Macintosh Archives (Quantum Leap)(CDRM1080320)(1993).iso / FILES / BBS / HERMES / ProtMover6.1.cpt / utility.c < prev    next >
C/C++ Source or Header  |  1990-05-29  |  23KB  |  956 lines

  1. #include "Protocol.h"
  2.  
  3. /*#define        APPLUTIL    {dummy}*/
  4.  
  5. char bEleven;
  6. ProtoRecHandle blPRH;
  7.  
  8. #ifndef APPLUTIL
  9. #include <:Mac #includes:SetUpA4.h>
  10. #endif
  11.  
  12. #ifndef APPLUTIL
  13. pascal OsErr main(message, prp, refCon)
  14. #else
  15. pascal OsErr UtilityMain(message, prp, refCon)
  16. #endif
  17. register int message;
  18. register ProtoRecPtr prp;
  19. long refCon;
  20. {
  21.     OsErr err = noErr;
  22.     ProcMenuHandle BuildProcMenu();
  23. #ifndef APPLUTIL
  24.     RememberA0();
  25.     SetUpA4();
  26. #endif
  27.     switch(message) {
  28.     case BUILDTMENU:
  29.     case BUILDDAMENU:
  30.     case BUILDMENU:
  31.         /*    ProcMenuHandle returned in prp, refCon contains
  32.             Transfer menu ID in hi word and mode in low word.
  33.         */
  34.         *((ProcMenuHandle *) prp) =
  35.             BuildProcMenu(message, HiWord(refCon), LoWord(refCon));
  36.         break;
  37.     case ABLEMENU:
  38.         if (prp) {
  39.             doEDItems(prp, (refCon != 0L));
  40.         }
  41.         break;
  42.     case DISPOSEMENU:
  43.         if (prp) {
  44.             doKillMenu(prp);
  45.         }
  46.         break;
  47.     case DISPOSEPREC:
  48.         if (prp) {
  49.             doKillPRec(prp);
  50.         }
  51.         break;
  52.     case DOMENU:
  53.         if (prp) {
  54.             doMenu(prp, HiWord(refCon), LoWord(refCon));
  55.         }
  56.         break;
  57.     }
  58. #ifndef APPLUTIL
  59.     RestoreA4();
  60. #endif
  61.     return(err);
  62. }
  63.  
  64. setFolder(mode)
  65. int mode;
  66. {
  67.     Point xyloc;
  68.     SFReply reply;
  69.     char vName[64];
  70.     long CurDirSave;
  71.     int DiskSave, vRef;
  72.     UtilPrefHandle UPH;
  73.     pascal int sfHook();
  74.     pascal char sfFilter();
  75.     register UtilPrefPtr upp;
  76.     CurDirSave = CurDirStore;
  77.     DiskSave = SFSaveDisk;
  78.     DLOGSetPt(900, &xyloc);
  79.     bEleven = FALSE;
  80. #ifndef APPLUTIL
  81.     RememberA4();
  82. #endif
  83.     SFPGetFile(xyloc, 0L, sfFilter, -1, 0L, sfHook, &reply, 900, 0L);
  84.     if (bEleven) {
  85.         /*    save the directory information */
  86.         UPH = (UtilPrefHandle) GetResource('DATA', 900);
  87.         if (UPH) {
  88.             HLock(UPH);
  89.             upp = *UPH;
  90.             if (mode == BBSMODE) {
  91.                 ++upp;
  92.             }
  93.             /*    get the volume name in a round about way */
  94.             GetVol(vName, &vRef);
  95.             SetVol(0L, -SFSaveDisk);
  96.             GetVol(upp->vName, &upp->CurDirStore);
  97.             upp->CurDirStore = CurDirStore;
  98.             SetVol(vName, vRef);
  99.             HUnlock(UPH);
  100.             ChangedResource(UPH);
  101.             WriteResource(UPH);
  102.         }
  103.     }
  104.     CurDirStore = CurDirSave;
  105.     SFSaveDisk = DiskSave;
  106. }
  107.  
  108. pascal char sfFilter(pBlock)
  109. ParmBlkPtr pBlock;
  110. {
  111.     /*    never open any files */
  112.     return((char) TRUE);
  113. }
  114.  
  115. pascal int sfHook(item, dp)
  116. int item;
  117. DialogPtr dp;
  118. {
  119. #ifndef APPLUTIL
  120.     SetUpA4();
  121. #endif
  122.     switch(item) {
  123.     case -1:
  124.         SetCtlTitle(11, "\pSet", dp);
  125.         break;
  126.     /*    Set */
  127.     case 11:
  128.         bEleven = TRUE;
  129.         item = 1;
  130.         break;
  131.     }
  132. #ifndef APPLUTIL
  133.     RestoreA4();
  134. #endif
  135.     return(item);
  136. }
  137.  
  138. doMenu(PMH, menuID, menuItem)
  139. ProcMenuHandle PMH;
  140. register int menuID;
  141. register int menuItem;
  142. {
  143.     int pmID, OK, vRef;
  144.     ProtoRecHandle PRH;
  145.     register int i, hID;
  146.     register ProcMenuPtr pmp;
  147.     register ProtoRecPtr prp;
  148.     pmp = *PMH;
  149.     pmID = (*pmp->pMenu)->menuID;
  150.     /*    find the matching entry */
  151.     for (i = 0; i<pmp->pCount; i++) {
  152.         if (pmID == menuID) {
  153.             /*    look at the itemID */
  154.             if (pmp->pList[i].itemID == menuItem) {
  155.                 break;
  156.             }
  157.         }
  158.         else {
  159.             /*    look for hierarchical menu item and hierarchical ID */
  160.             if ((pmp->pList[i].HitemID == menuItem) &&
  161.                 (pmp->pList[i].HmenuID == menuID)) {
  162.                 break;
  163.             }
  164.         }
  165.     }
  166.     if (i < pmp->pCount) {
  167.         /*    we found a match so let's do it */
  168.         /*    start by building a ProtoRec */
  169.         PRH = (ProtoRecHandle) NewHandle((long) sizeof(ProtoRec));
  170.         pmp = *PMH;
  171.         if (PRH) {
  172.             prp = *PRH;
  173.             if (pmp->pList[i].funcMask & (CANSEN+CANBSEN)) {
  174.                 pmp->transMessage = SEND;
  175.             }
  176.             else if (pmp->pList[i].funcMask & (CANREC+CANBREC)) {
  177.                 pmp->transMessage = RECEIVE;
  178.             }
  179.             else {
  180.                 pmp->transMessage = SETPREFS;
  181.             }
  182.             pmp->transRefCon = pmp->pList[i].refCon;
  183.             pmp->transIndex = i;
  184.             /*    prp->mRefIn, mRefOut, timeOut to be filled out by caller */
  185.             prp->procID = pmp->pList[i].procID;
  186.             prp->protoData = 0L;
  187.             prp->errReason = 0L;
  188.             prp->fileCount = 0;
  189.             prp->filesDone = 0;
  190.             prp->bytesDone = 0L;
  191.             prp->bytesTotal = 0L;
  192.             prp->F.word = 0;
  193.             prp->F.B.useMacBinary = TRUE;
  194.             prp->F.B.transMode = pmp->pMode;
  195.             HLock(PMH);
  196.             OK = TRUE;
  197.             switch(pmp->transMessage) {
  198.             case SETPREFS:
  199.                 (*PRH)->fileCount = 0;
  200.                 break;
  201.             case SEND:
  202.                 /*    get list of files to send */
  203.                 OK = getTransList(PRH, pmp->pList[i].pFlags & CANBSEN);
  204.                 break;
  205.             case RECEIVE:
  206.                 /*    get a working directory for the receive folder */
  207.                 getVRef(&vRef, (*PRH)->F.B.transMode);
  208.                 if ((*PRH)->F.B.transMode == BBSMODE) {
  209.                     if (pmp->pList[i].pFlags & CANBREC) {
  210.                         /*    set up batch receive test files */
  211.                         addName(PRH, vRef, "\pBBS Batch Upload A", 0L,
  212.                             pmp->pList[i].pFlags & CONTREC);
  213.                         addName(PRH, vRef, "\pBBS Batch Upload B", 0L,
  214.                             pmp->pList[i].pFlags & CONTREC);
  215.                         addName(PRH, vRef, "\pBBS Batch Upload C", 0L,
  216.                             pmp->pList[i].pFlags & CONTREC);
  217.                     }
  218.                     else {
  219.                         /*    set up receive files for BBS */
  220.                         addName(PRH, vRef, "\pBBS Upload", 0L,
  221.                             pmp->pList[i].pFlags & CONTREC);
  222.                     }
  223.                 }
  224.                 else {
  225.                     /*    set up receive folder for terminal */
  226.                     addName(PRH, vRef, "\pDownload File", 0L,
  227.                         pmp->pList[i].pFlags & CONTREC);
  228.                 }
  229.                 break;
  230.             }
  231.             HUnlock(PMH);
  232.             MoveHHi(PRH);
  233.             HLock(PRH);
  234.             pmp = *PMH;
  235.             pmp->transData = PRH;
  236.             (*PRH)->startTime = TickCount();
  237.             if (!OK) {
  238.                 /*    Dispose of everyting we created */
  239.                 doKillPRec(PMH);
  240.             }
  241.         }
  242.     }
  243.     else if (menuItem == pmp->foldID) {
  244.         setFolder(pmp->pMode);
  245.     }
  246.     else if (menuItem == pmp->helpID) {
  247.         doHelp(pmp->doUpdate);
  248.     }
  249. }
  250.  
  251. int getTransList(prh, batch)
  252. register ProtoRecHandle prh;
  253. int batch;
  254. {
  255.     int i = 1;
  256.     Point xyloc;
  257.     SFReply reply;
  258.     Str255 text1, text2;
  259.     pascal int blHook();
  260.     pascal char blFilter();
  261.     blPRH = prh;
  262.     do {
  263.         DLOGSetPt(900, &xyloc);
  264.         bEleven = FALSE;
  265.         if (!batch) {
  266.             bEleven = -1;
  267.         }
  268. #ifndef APPLUTIL
  269.         RememberA4();
  270. #endif
  271.         SFPGetFile(xyloc, 0L, blFilter, -1, 0L, blHook, &reply, 900, 0L);
  272.         if (reply.good) {
  273.             /*    add name to list */
  274.             if ((*prh)->F.B.transMode == BBSMODE) {
  275.                 /*    fill in MacBinary names */
  276.                 Pstrcpy(text1, "\pMacBinary Name ");
  277.                 NumToString((long) i++, text2);
  278.                 Pstrcat(text1, text2);
  279.                 addName(prh, reply.vRefNum, reply.fName, text1, -1);
  280.             }
  281.             else {
  282.                 addName(prh, reply.vRefNum, reply.fName, 0L, -1);
  283.             }
  284.         }
  285.     } while (bEleven == TRUE);
  286.     return(reply.good);
  287. }
  288.  
  289. pascal char blFilter(pBlock)
  290. ParmBlkPtr pBlock;
  291. {
  292.     char noShow;
  293.     register int i;
  294.     register FListPtr flp;
  295. #ifndef APPLUTIL
  296.     SetUpA4();
  297. #endif
  298.     noShow = FALSE;
  299.     flp = (*blPRH)->fList;
  300.     for (i = 0; i<(*blPRH)->fileCount; i++) {
  301.         if (EqualString(*flp[i].fName, pBlock->fileParam.ioNamePtr, TRUE, TRUE)) {
  302.             noShow = TRUE;
  303.             break;
  304.         }
  305.     }
  306. #ifndef APPLUTIL
  307.     RestoreA4();
  308. #endif
  309.     return(noShow);
  310. }
  311.  
  312. pascal int blHook(item, dp)
  313. int item;
  314. DialogPtr dp;
  315. {
  316. #ifndef APPLUTIL
  317.     SetUpA4();
  318. #endif
  319.     switch(item) {
  320.     case -1:
  321.         SetCtlTitle(1, "\pSend", dp);
  322.         SetCtlTitle(11, "\pBatch", dp);
  323.         if (bEleven < 0) {
  324.             ActItem(11, FALSE, dp);
  325.         }
  326.         break;
  327.     /*    Set */
  328.     case 11:
  329.         bEleven = TRUE;
  330.         item = 1;
  331.         break;
  332.     }
  333. #ifndef APPLUTIL
  334.     RestoreA4();
  335. #endif
  336.     return(item);
  337. }
  338.  
  339. addName(prh, vRef, fName, bName, recover)
  340. register ProtoRecHandle prh;
  341. int vRef;
  342. StringPtr fName, bName;
  343. int recover;
  344. {
  345.     OsErr err;
  346.     FInfo fInfo;
  347.     FListRec FLR;
  348.     register int i;
  349.     WDPBRec myWDPBRec;
  350.     Str255 text2, text1;
  351.     Pstrcpy(text2, fName);
  352.     i = 0;
  353.     FLR.mbName = 0L;
  354.     FLR.vRefNum = vRef;
  355.     FLR.dirID = 0L;
  356.     FLR.fileID = 0L;
  357.     if (recover >=0 ) {
  358.         for (;;) {
  359.             err = GetFInfo(text2, FLR.vRefNum, &fInfo);
  360.             if (err) {
  361.                 break;
  362.             }
  363.             if ((i == 0) && recover && (fInfo.fdType == 'FRAG')) {
  364.                 break;
  365.             }
  366.             ++i;
  367.             NumToString((long) i, text1);
  368.             Pstrcpy(text2, fName);
  369.             Pstrcad(text2, ' ');
  370.             Pstrcat(text2, text1);
  371.         }
  372.     }
  373.     FLR.fName = NewString(text2);
  374.     if (bName) {
  375.         FLR.mbName = NewString(bName);
  376.     }
  377.     else {
  378.         FLR.mbName = 0L;
  379.     }
  380.     /*    convert the working directory into a dirID */
  381.     myWDPBRec.ioCompletion = 0L;
  382.     myWDPBRec.ioNamePtr = 0L;
  383.     myWDPBRec.ioVRefNum = FLR.vRefNum;
  384.     myWDPBRec.ioWDIndex = 0;
  385.     myWDPBRec.ioWDProcID = 0L;
  386.     myWDPBRec.ioWDVRefNum = 0;
  387.     myWDPBRec.ioWDDirID = 0L;
  388.     err = PBGetWDInfo(&myWDPBRec, FALSE);
  389.     if (!err) {
  390.         FLR.dirID = myWDPBRec.ioWDDirID;
  391.     }
  392.     SetHandleSize(prh, GetHandleSize(prh)+sizeof(FListRec));
  393.     (*prh)->fList[(*prh)->fileCount] = FLR;
  394.     ++(*prh)->fileCount;
  395. }
  396.  
  397. getVRef(vRefPtr, mode)
  398. register int *vRefPtr;
  399. int mode;
  400. {
  401.     int vRef;
  402.     OsErr err;
  403.     WDPBRec myWDPBRec;
  404.     UtilPrefHandle UPH;
  405.     register UtilPrefPtr upp;
  406.     /*    get the vRefNum from the DATA resource */
  407.     *vRefPtr = 0;
  408.     UPH = (UtilPrefHandle) GetResource('DATA', 900);
  409.     if (UPH) {
  410.         HLock(UPH);
  411.         upp = *UPH;
  412.         if (mode == BBSMODE) {
  413.             ++upp;
  414.         }
  415.         /*    open a working directory */
  416.         myWDPBRec.ioCompletion = 0L;
  417.         myWDPBRec.ioNamePtr = 0L;
  418.         GetVol(0L, &vRef);
  419.         SetVol(&upp->vName, 0);
  420.         GetVol(0L, &myWDPBRec.ioVRefNum);
  421.         SetVol(0L, vRef);
  422.         myWDPBRec.ioWDProcID = 'ERIK';
  423.         myWDPBRec.ioWDDirID = upp->CurDirStore;
  424.         err = PBOpenWD(&myWDPBRec, FALSE);
  425.         if (!err) {
  426.             *vRefPtr = myWDPBRec.ioVRefNum;
  427.         }
  428.         HUnlock(UPH);
  429.     }
  430. }
  431.  
  432. doKillPRec(pmh)
  433. register ProcMenuHandle pmh;
  434. {
  435.     register int i;
  436.     register ProtoRecPtr prp;
  437.     if ((*pmh)->transData) {
  438.         prp = *(*pmh)->transData;
  439.         for (i = 0; i<prp->fileCount; i++) {
  440.             if (prp->fList[i].fName) {
  441.                 DisposHandle(prp->fList[i].fName);
  442.             }
  443.             if (prp->fList[i].mbName) {
  444.                 DisposHandle(prp->fList[i].mbName);
  445.             }
  446.         }
  447.         HUnlock((*pmh)->transData);
  448.         DisposHandle((*pmh)->transData);
  449.         (*pmh)->transData = 0L;
  450.     }
  451. }
  452.  
  453. doKillMenu(pmh)
  454. register ProcMenuHandle pmh;
  455. {
  456.     register int i, hID;
  457.     register MenuHandle hmh;
  458.     for (i = (*pmh)->firstID; i<=(*pmh)->helpID; i++) {
  459.         DelMenuItem((*pmh)->pMenu, (*pmh)->firstID);
  460.     }
  461.     for (i = 0; i<(*pmh)->pCount; i++) {
  462.         hID = (*pmh)->pList[i].HmenuID;
  463.         if ((*pmh)->pList[i].HitemID == 1) {
  464.             hmh = GetMHandle(hID);
  465.             DeleteMenu(hID);
  466.             DisposeMenu(hmh);
  467.         }
  468.         DisposHandle((*pmh)->pList[i].subName);
  469.     }
  470.     DisposHandle((*pmh)->autoComs);
  471.     DisposHandle(pmh);
  472. }
  473.  
  474. doEDItems(pmh, state)
  475. register ProcMenuHandle pmh;
  476. register int state;
  477. {
  478.     register int i;
  479.     register MenuHandle pMenu;
  480.     pMenu = (*pmh)->pMenu;
  481.     for (i = 0; i<(*pmh)->pCount; i++) {
  482.         EDItem(pMenu, (*pmh)->pList[i].itemID, state);
  483.     }
  484.     EDItem(pMenu, (*pmh)->foldID, state);
  485.     EDItem(pMenu, (*pmh)->helpID, state);
  486. }
  487.  
  488. EDItem(menu, item, state)
  489. MenuHandle menu;
  490. int item, state;
  491. {
  492.     if (state) {
  493.         EnableItem(menu, item);
  494.     }
  495.     else {
  496.         DisableItem(menu, item);
  497.     }
  498. }
  499.  
  500. ProcMenuHandle BuildProcMenu(message, pMenuID, mode)
  501. int message;
  502. int pMenuID;
  503. int mode;
  504. {
  505.     int hBase;
  506.     MenuHandle pMenu;
  507.     register ProcMenuHandle pmh;
  508.     pMenu = GetMHandle(pMenuID);
  509.     pmh = (ProcMenuHandle) NewHandle((long) sizeof(ProcMenu));
  510.     (*pmh)->doUpdate = 0L;
  511.     (*pmh)->pMode = mode;
  512.     (*pmh)->pMenu = pMenu;
  513.     (*pmh)->transData = 0L;
  514.     (*pmh)->pCount = 0;
  515.     (*pmh)->firstID = CountMItems(pMenu)+1;
  516.     (*pmh)->foldID = CountMItems(pMenu);
  517.     (*pmh)->autoCount = 0;
  518.     (*pmh)->autoComs = (AutoComHandle) NewHandle(0L);
  519.     if (message == BUILDDAMENU) {
  520.         /*    DAs can have hierarchical menu IDs from 236 to 255 */
  521.         /*    ALL OF THESE IDs MIGHT BE USED BY PROTOCOLS!!!! */
  522.         hBase = 236;
  523.     }
  524.     else {
  525.         /*    applications can have hierarchical menu IDs from 0 to 235 */
  526.         /*    OF WHICH 216 TO 235 MIGHT BE USED BY PROTOCOLS!!!! */
  527.         hBase = 216;
  528.     }
  529.     if ((message == BUILDTMENU) || (mode == TERMINALMODE) || 
  530.         (message == BUILDDAMENU)) {
  531.         /*    add all possible protocols */
  532.         AddProcSubs(CANSEN+CANBSEN, pmh, hBase);
  533.         if (mode == TERMINALMODE) {
  534.             AddProcSubs(CANREC, pmh, hBase);
  535.             AddProcSubs(SETERMPREF, pmh, hBase);
  536.         }
  537.         else {
  538.             AddProcSubs(CANREC+CANBREC, pmh, hBase);
  539.             AddProcSubs(SETBBSPREF, pmh, hBase);
  540.         }
  541.         if ((*pmh)->foldID) {
  542.             (*pmh)->foldID += 2;
  543.             (*pmh)->helpID = (*pmh)->foldID+2;
  544.             AppendMenu(pMenu, "\p(-;Set Receive Folder;(-;Help");
  545.         }
  546.     }
  547.     else {
  548.         /*    only add the prefs and help items in BBS mode */
  549.         AddProcSubs(SETERMPREF, pmh, hBase);
  550.         if ((*pmh)->foldID) {
  551.             (*pmh)->foldID += 2;
  552.             (*pmh)->helpID = (*pmh)->foldID;
  553.             (*pmh)->foldID = -1;
  554.             AppendMenu(pMenu, "\p(-;Help");
  555.         }
  556.     }
  557.     return(pmh);
  558. }
  559.  
  560. int AddProcSubs(mask, pmh, hBase)
  561. int mask;
  562. ProcMenuHandle pmh;
  563. int hBase;
  564. {
  565.     ProcSub SF;
  566.     ResType rType;
  567.     PInfHandle pHand;
  568.     MenuHandle hMenu;
  569.     char needBar, newItem;
  570.     Str255 rName, lastName;
  571.     register ProcMenuPtr pmp;
  572.     int pID, hID, firstID, itemID, subCount, hCount, i, j;
  573.     HLock(pmh);
  574.     pmp = *pmh;
  575.     firstID = pmp->foldID;
  576.     needBar = (pmp->foldID != 0);
  577.     /*    loop through all of the possible PROC IDs */
  578.     for (i = 0; i<PROCINDEX; i++) {
  579.         pID = i*100+1000;
  580.         hID = i+hBase;
  581.         if (mask & (CANREC+CANBREC)) {
  582.             hID += PROCINDEX;
  583.         }
  584.         pHand = (PInfHandle) Get1Resource('PInf', pID);
  585.         if (pHand) {
  586.             hCount = 0;
  587.             hMenu = 0L;
  588.             newItem = FALSE;
  589.             itemID = pmp->foldID;
  590.             subCount = (*pHand)->SubCount;
  591.             GetResInfo(pHand, &pID, &rType, rName);
  592.             for (j = 0; j<subCount; j++) {
  593.                 GetSubFunction(&SF, pID, j+1);
  594.                 if (rName[0] && SF.subName[0] && (mask & SF.pFlags)) {
  595.                     ++hCount;
  596.                     if (needBar) {
  597.                         /*    add a split bar */
  598.                         ++itemID;
  599.                         ++firstID;
  600.                         ++pmp->foldID;
  601.                         AppendMenu(pmp->pMenu, "\p(-"); /* ) */
  602.                         needBar = FALSE;
  603.                     }
  604.                     /*    first, add this to the PROC menu list */
  605.                     HUnlock(pmh);
  606.                     SetHandleSize(pmh, GetHandleSize(pmh)+sizeof(ProcList));
  607.                     HLock(pmh);
  608.                     pmp = *pmh;
  609.                     pmp->pList[pmp->pCount].procID = pID;
  610.                     pmp->pList[pmp->pCount].itemID = itemID+1;
  611.                     pmp->pList[pmp->pCount].subName = NewString(SF.subName);
  612.                     pmp->pList[pmp->pCount].funcMask = mask;
  613.                     pmp->pList[pmp->pCount].pFlags = SF.pFlags;
  614.                     pmp->pList[pmp->pCount].refCon = SF.refCon;
  615.                     if (SF.autoCom[0] && (mask & CANREC+CANBREC)) {
  616.                         addAutoCom(pmp, (*pmp->pMenu)->menuID, itemID+1, SF.autoCom);
  617.                     }
  618.                     if (hCount > 1) {
  619.                         if (hCount == 2) {
  620.                             /*    make hierarchical menu for last choice */
  621.                             pmp->pList[pmp->pCount-1].HmenuID = hID;
  622.                             pmp->pList[pmp->pCount-1].HitemID = 1;
  623.                             hMenu = NewMenu(hID, rName);
  624.                             /*    add a new hierarchical menu item and stop any
  625.                                 funny business
  626.                             */
  627.                             AppendMenu(hMenu, "\pJR Was Here");
  628.                             /*    hierarchical item text comes from PInf resource */
  629.                             Pstrcad(lastName, '…');
  630.                             SetItem(hMenu, 1, lastName);
  631.                             InsertMenu(hMenu, -1);
  632.                             /*    adjust any auto receive commands */
  633.                             swapAutoCom(pmp, (*pmp->pMenu)->menuID, itemID+1,
  634.                                             hID, 1);
  635.                         }
  636.                         pmp->pList[pmp->pCount].HmenuID = hID;
  637.                         pmp->pList[pmp->pCount].HitemID = hCount;
  638.                         /*    add a new hierarchical menu item and stop any
  639.                             funny business
  640.                         */
  641.                         AppendMenu(hMenu, "\pJR Was Here");
  642.                         /*    hierarchical item text comes from PInf resource */
  643.                         Pstrcad(SF.subName, '…');
  644.                         SetItem(hMenu, hCount, SF.subName);
  645.                         /*    adjust any auto receive commands */
  646.                         swapAutoCom(pmp, (*pmp->pMenu)->menuID, itemID+1,
  647.                                         hID, hCount);
  648.                     }
  649.                     else {
  650.                         pmp->pList[pmp->pCount].HmenuID = 0;
  651.                         pmp->pList[pmp->pCount].HitemID = 0;
  652.                     }
  653.                     if (hCount == 1) {
  654.                         newItem = TRUE;
  655.                         ++pmp->foldID;
  656.                         /*    add a new main menu item and stop any funny business */
  657.                         AppendMenu(pmp->pMenu, "\pJR Was Here");
  658.                         /*    main item text comes from PInf resource name */
  659.                         lastName[0] = 0;
  660.                         if (mask & (CANSEN+CANBSEN)) {
  661.                             /*    add Send prefix */
  662.                             Pstrcpy(lastName, "\pSend ");
  663.                         }
  664.                         else if (mask & (CANREC+CANBREC)) {
  665.                             /*    add Receive prefix */
  666.                             Pstrcpy(lastName, "\pReceive ");
  667.                         }
  668.                         else if (mask & (SETERMPREF+SETBBSPREF)) {
  669.                             /*    add Set prefix */
  670.                             Pstrcpy(lastName, "\pSet ");
  671.                         }
  672.                         Pstrcat(lastName, rName);
  673.                         Pstrcpy(rName, lastName);
  674.                         SetItem(pmp->pMenu, pmp->foldID, rName);
  675.                     }
  676.                     Pstrcpy(lastName, SF.subName);
  677.                     ++pmp->pCount;
  678.                 }
  679.             }
  680.             if (newItem) {
  681.                 if (hMenu) {
  682.                     SortProcMenu(pmp, hMenu, 1, hCount);
  683.                     SetItemCmd(pmp->pMenu, pmp->foldID, 0x1B);
  684.                     SetItemMark(pmp->pMenu, pmp->foldID, hID);
  685.                 }
  686.                 else {
  687.                     /*    tack a … on to the end of the menu item */
  688.                     Pstrcad(rName, '…');
  689.                     SetItem(pmp->pMenu, pmp->foldID, rName);
  690.                 }
  691.             }
  692.             /*    we are not going to use 'PInf' again... */
  693.             ReleaseResource(pHand);
  694.         }
  695.     }
  696.     SortProcMenu(pmp, pmp->pMenu, firstID, pmp->foldID);
  697.     HUnlock(pmh);
  698. }
  699.  
  700. SortProcMenu(pmp, pMenu, fromItem, toItem)
  701. register ProcMenuPtr pmp;
  702. MenuHandle pMenu;
  703. int fromItem, toItem;
  704. {
  705.     Str255 itemText1, itemText2;
  706.     int done, mark1, mark2, cmd1, cmd2;
  707.     int jump, n, i, j, k, mID, pmID, item1, item2;
  708.     mID = (*pMenu)->menuID;
  709.     pmID = (*pmp->pMenu)->menuID;
  710.     /*    remember to move command AND mark keys too */
  711.     n = toItem-fromItem+1;
  712.     jump = n;
  713.     while (jump > 1) {
  714.         jump /= 2;
  715.         do {
  716.             done = TRUE;
  717.             for (j = 0; j<n-jump; j++) {
  718.                 i = j + jump;
  719.                 item1 = i+fromItem;
  720.                 item2 = j+fromItem;
  721.                 /*    get menu item 1 data */
  722.                 GetItem(pMenu, item1, itemText1);
  723.                 GetItemMark(pMenu, item1, &mark1);
  724.                 GetItemCmd(pMenu, item1, &cmd1);
  725.                 /*    get menu item 2 data */
  726.                 GetItem(pMenu, item2, itemText2);
  727.                 GetItemMark(pMenu, item2, &mark2);
  728.                 GetItemCmd(pMenu, item2, &cmd2);
  729.                 if (IUCompString(itemText2, itemText1) > 0) {
  730.                     /*    swap item data */
  731.                     SetItem(pMenu, item1, itemText2);
  732.                     SetItemMark(pMenu, item1, mark2);
  733.                     SetItemCmd(pMenu, item1, cmd2);
  734.                     SetItem(pMenu, item2, itemText1);
  735.                     SetItemMark(pMenu, item2, mark1);
  736.                     SetItemCmd(pMenu, item2, cmd1);
  737.                     /*    fix the auto receives */
  738.                     swapAutoCom(pmp, mID, item1, mID, item2);
  739.                     /*    fix the pList */
  740.                     for (k = 0; k<pmp->pCount; k++) {
  741.                         if (pmID == mID) {
  742.                             /*    look at the itemID */
  743.                             if (pmp->pList[k].itemID == item1) {
  744.                                 pmp->pList[k].itemID = item2;
  745.                             }
  746.                             else if (pmp->pList[k].itemID == item2) {
  747.                                 pmp->pList[k].itemID = item1;
  748.                             }
  749.                         }
  750.                         else {
  751.                             /*    look for hierarchical menu item and hierarchical ID */
  752.                             if (pmp->pList[k].HmenuID == mID) {
  753.                                 if (pmp->pList[k].HitemID == item1) {
  754.                                     pmp->pList[k].HitemID = item2;
  755.                                 }
  756.                                 else if (pmp->pList[k].HitemID == item2) {
  757.                                     pmp->pList[k].HitemID = item1;
  758.                                 }
  759.                             }
  760.                         }
  761.                     }
  762.                     done = FALSE;
  763.                 }
  764.             }
  765.         } while(!done);
  766.     }
  767. }
  768.  
  769. GetSubFunction(SFP, ID, index)
  770. register ProcSub *SFP;
  771. int ID;
  772. register int index;
  773. {
  774.     int sCount;
  775.     PInfHandle pInf;
  776.     register unsigned char *sfp;
  777.     /*    set default for not found condition */
  778.     SFP->pFlags = 0;
  779.     SFP->refCon = 0;
  780.     SFP->subName[0] = 0;
  781.     /*    try to get the resource */
  782.     pInf = (PInfHandle) GetResource('PInf', ID);
  783.     if (pInf) {
  784.         /*    get the number of sub functions described in the resource */
  785.         sCount = (*pInf)->SubCount;
  786.         if ((sCount > 0) && (sCount >= index)) {
  787.             sfp = (unsigned char *) *pInf;
  788.             /*    bump past the count word */
  789.             sfp += 2;
  790.             /*    bump through sub descriptions until we get to the right one */
  791.             while (--index) {
  792.                 /*    bump past the non-string stuff */
  793.                 sfp = (unsigned char *) (&(((ProcSub *) sfp)->subName));
  794.                 /*    bump past the name string (with padding) */
  795.                 sfp += *sfp+2-(*sfp & 1);
  796.                 /*    bump past the auto string (with padding) */
  797.                 sfp += *sfp+2-(*sfp & 1);
  798.             }
  799.             /*    extract the data */
  800.             SFP->pFlags = ((ProcSub *) sfp)->pFlags;
  801.             SFP->refCon = ((ProcSub *) sfp)->refCon;
  802.             sfp = (unsigned char *) (&(((ProcSub *) sfp)->subName));
  803.             Pstrcpy(SFP->subName, sfp);
  804.             sfp += *sfp+2-(*sfp & 1);
  805.             Pstrcpy(SFP->autoCom, sfp);
  806.         }
  807.     }
  808. }
  809.  
  810. addAutoCom(pmp, menuSelect, autoComs)
  811. register ProcMenuPtr pmp;
  812. long menuSelect;
  813. unsigned char *autoComs;
  814. {
  815.     register int i;
  816.     Str255 autoStr;
  817.     long offset, size;
  818.     register AutoComPtr acp;
  819.     autoStr[0] = 0;
  820.     for (i = 1; i<=autoComs[0]; i++) {
  821.         if (autoComs[i] != ',') {
  822.             Pstrcad(autoStr, autoComs[i]);
  823.         }
  824.         else if ((i < autoComs[0]) && (autoComs[i+1] == ',')) {
  825.             Pstrcad(autoStr, autoComs[i]);
  826.             continue;
  827.         }
  828.         if (autoStr[0] && ((i == autoComs[0]) || (autoComs[i] == ','))) {
  829.             /*    add the auto string */
  830.             offset = GetHandleSize(pmp->autoComs);
  831.             size = sizeof(AutoComRec)+autoStr[0]+2-(autoStr[0] & 1);
  832.             SetHandleSize(pmp->autoComs, offset+size);
  833.             acp = (AutoComPtr) (((unsigned char *) *pmp->autoComs) + offset);
  834.             acp->matchChar = 1;
  835.             acp->menuSelect = menuSelect;
  836.             Pstrcpy(acp->autoCom, autoStr);
  837.             ++pmp->autoCount;
  838.             autoStr[0] = 0;
  839.         }
  840.     }
  841. }
  842.  
  843. swapAutoCom(pmp, menuSelect1, menuSelect2)
  844. register ProcMenuPtr pmp;
  845. long menuSelect1, menuSelect2;
  846. {
  847.     register int i;
  848.     register unsigned char *acp;
  849.     acp = (unsigned char *) *pmp->autoComs;
  850.     for (i = 0; i<pmp->autoCount; i++) {
  851.         if (((AutoComPtr) acp)->menuSelect == menuSelect1) {
  852.             ((AutoComPtr) acp)->menuSelect = menuSelect2;
  853.         }
  854.         else if (((AutoComPtr) acp)->menuSelect == menuSelect2) {
  855.             ((AutoComPtr) acp)->menuSelect = menuSelect1;
  856.         }
  857.         /*    bump past the non-string stuff */
  858.         acp = (unsigned char *) (&(((AutoComPtr) acp)->autoCom));
  859.         /*    bump past the auto string (with padding) */
  860.         acp += *acp+2-(*acp & 1);
  861.     }
  862. }
  863.  
  864. doHelp(update)
  865. void (*update)();
  866. {
  867.     int item;
  868.     long callHelp();
  869.     Block_Record hRec;
  870.     pascal void DealUpdates();
  871.     Pstrcpy(hRec.message,
  872.         "\p\rProtocol Interface\rCopyright © 1990 by John Raymonds");
  873.     Pstrcat(hRec.message,
  874.         "\p\r\rHelp System\rCopyright © 1989 By Eric Berman");
  875.     hRec.Help_Type = 'Thlp';
  876.     hRec.Num_Types = 1;
  877.     hRec.Res_Types = (ResType *) "Thlp";
  878.     SetPt(&hRec.upper_Left, 0, 0);
  879.     hRec.update_Proc = update;
  880.     hRec.map_Hook = 0L;
  881.     /*    get list of topics */
  882.     hRec.topic_List = (Help_List_Handle)
  883.                             callHelp(&hRec, GetTopicList_Trap);
  884.     if (hRec.topic_List) {
  885.         /*    and sort them */
  886.         callHelp(&hRec, ShellSort_Trap);
  887.         /*    display the help items */
  888.         hRec.Dialog_ID = Text_List_ID;
  889.         hRec.the_Help = (Handle) callHelp(&hRec, TextMenu_Trap);
  890.         /*    do event loop for help system */
  891.         do {
  892.             hRec.Dialog_ID = Topic_Window_ID;
  893.             item = callHelp(&hRec, ShowTopicList_Trap);
  894.             if (item == 2) {
  895.                 /*    display the help items */
  896.                 hRec.Dialog_ID = Text_List_ID;
  897.                 hRec.the_Help = (Handle) callHelp(&hRec, TextMenu_Trap);
  898.             }
  899.         } while(item != 1);
  900.         DisposHandle(hRec.topic_List);
  901.     }
  902. }
  903.  
  904. long callHelp(hRecPtr, theMessage)
  905. register Block_Ptr hRecPtr;
  906. int theMessage;
  907. {
  908.     long gtl();
  909.     register long result;
  910.     register long (**the_Code)();
  911.     result = 0L;
  912.     if (theMessage == GetTopicList_Trap) {
  913.         return(gtl(hRecPtr));
  914.     }
  915.     hRecPtr->varCode = theMessage;
  916.     the_Code = (long (** )()) GetResource('PROC', 901);
  917.     if (the_Code) {
  918.         MoveHHi(the_Code);
  919.         HLock(the_Code);
  920.         result = CallPascalL(hRecPtr, *the_Code);
  921.         HUnlock(the_Code);
  922.     }
  923.     return(result);
  924. }
  925.  
  926. long gtl(hRecPtr)
  927. register Block_Ptr hRecPtr;
  928. {
  929.     Handle rHand;
  930.     Help_List_Handle hHand;
  931.     register int Num_Topics, i;
  932.     register Help_List_Ptr hPtr;
  933.     /*    my code can only handle one help type */
  934.     hHand = 0L;
  935.     Num_Topics = Count1Resources(*hRecPtr->Res_Types);
  936.     if (Num_Topics) {
  937.         hHand = (Help_List_Handle)
  938.             NewHandle((long) (sizeof(Help_List_Type) * Num_Topics));
  939.         if (hHand) {
  940.             HLock(hHand);
  941.             hPtr = *hHand;
  942.             SetResLoad(FALSE);
  943.             for (i = 0; i<Num_Topics; i++) {
  944.                 rHand = Get1IndResource(*hRecPtr->Res_Types, i+1);
  945.                 if (rHand) {
  946.                     GetResInfo(rHand, &hPtr[i].help_ID,
  947.                         &hPtr[i].help_Type, &hPtr[i].help_String);
  948.                 }
  949.             }
  950.             SetResLoad(TRUE);
  951.             HUnlock(hHand);
  952.         }
  953.     }
  954.     return((long) hHand);
  955. }
  956.